use crate::cmp::{Cmp, DefaultCmp};
use crate::types::{current_key_val, LdbIterator};

use bytes::Bytes;
use std::cmp::Ordering;

/// TestLdbIter is an LdbIterator over a vector, to be used for testing purposes.
pub struct TestLdbIter<'a> {
    v: Vec<(&'a [u8], &'a [u8])>,
    ix: usize,
    init: bool,
}

impl<'a> TestLdbIter<'a> {
    pub fn new(c: Vec<(&'a [u8], &'a [u8])>) -> TestLdbIter<'a> {
        TestLdbIter {
            v: c,
            ix: 0,
            init: false,
        }
    }
}

impl LdbIterator for TestLdbIter<'_> {
    fn advance(&mut self) -> bool {
        println!("----------test advance----------");
        if self.ix == self.v.len() - 1 {
            self.ix += 1;
            false
        } else if !self.init {
            self.init = true;
            true
        } else {
            self.ix += 1;
            true
        }
    }
    fn reset(&mut self) {
        println!("----------test reset----------");
        self.ix = 0;
        self.init = false;
    }
    fn current(&self) -> Option<(Bytes, Bytes)> {
        println!("----------test current----------");
        if self.init && self.ix < self.v.len() {
            Some((
                Bytes::copy_from_slice(self.v[self.ix].0),
                Bytes::copy_from_slice(self.v[self.ix].1),
            ))
        } else {
            None
        }
    }
    fn valid(&self) -> bool {
        println!("----------test valid----------");
        self.init && self.ix < self.v.len()
    }
    fn seek(&mut self, k: &[u8]) {
        println!("----------test seek----------");
        self.ix = 0;
        self.init = true;
        while self.ix < self.v.len() && DefaultCmp.cmp(self.v[self.ix].0, k) == Ordering::Less {
            self.ix += 1;
        }
    }
    fn prev(&mut self) -> bool {
        println!("----------test prev----------");
        if !self.init || self.ix == 0 {
            self.init = false;
            false
        } else {
            self.ix -= 1;
            true
        }
    }
}

/// LdbIteratorIter implements std::iter::Iterator for an LdbIterator.
pub struct LdbIteratorIter<'a, It: 'a> {
    inner: &'a mut It,
}

impl<'a, It: LdbIterator> LdbIteratorIter<'a, It> {
    pub fn wrap(it: &'a mut It) -> LdbIteratorIter<'a, It> {
        LdbIteratorIter { inner: it }
    }
}

impl<It: LdbIterator> Iterator for LdbIteratorIter<'_, It> {
    type Item = (Vec<u8>, Vec<u8>);
    fn next(&mut self) -> Option<Self::Item> {
        LdbIterator::next(self.inner)
    }
}

/// This shared test takes an iterator with exactly four elements and tests that it fulfills the
/// generic iterator properties. Every iterator defined in this code base should pass this test.
///
/// 这段代码是一个通用的迭代器测试函数 test_iterator_properties，用于验证实现了 SSIterator trait 的迭代器是否符合预期的行为规范。
/// 它通过一系列断言来检查迭代器的各种基本操作和状态是否正确，确保迭代器的行为一致且可靠。
///
/// 核心目的：
///
/// 这个测试确保所有实现 SSIterator trait 的迭代器都遵循相同的行为契约，包括：
///
/// 正确的初始状态和有效性切换
///
/// 正向迭代（advance()）的正确性
///
/// 后退操作（prev()）的正确性
///
/// 查找操作（seek()）的正确性
///
/// 重置（reset()）功能的正确性
pub fn test_iterator_properties<It: LdbIterator>(mut it: It) {
    // 验证新创建的迭代器初始状态为 !valid()（无效）
    assert!(!it.valid());
    // 调用 advance() 方法四次，每次前进到下一个元素
    assert!(it.advance());
    // 每次前进后验证迭代器处于 valid()（有效）状态
    assert!(it.valid());
    // 记录每个位置的键值对，并验证 current_key() 返回的键与实际键一致
    let first = current_key_val(&it);
    assert!(it.advance());
    let second = current_key_val(&it);
    assert!(it.advance());
    let third = current_key_val(&it);
    // fourth (last) element
    assert!(it.advance());
    assert!(it.valid());
    let fourth = current_key_val(&it);
    // past end is invalid
    // 第四次前进后（到达最后一个元素），再次调用 advance() 应返回 false，且迭代器状态变为 !valid()
    assert!(!it.advance());
    assert!(!it.valid());

    it.reset();
    // 重置迭代器后，测试 seek() 方法能否正确定位到指定键（第四个元素和第二个元素）
    it.seek(&fourth.as_ref().unwrap().0);
    assert!(it.valid());
    it.seek(&second.as_ref().unwrap().0);
    assert!(it.valid());
    // 定位到第二个元素后，调用 prev() 应后退到第一个元素
    it.prev();
    assert_eq!(first, current_key_val(&it));

    // 再次重置迭代器，验证正向迭代能正确访问前三个元素
    it.reset();
    assert!(!it.valid());
    assert!(it.advance());
    assert_eq!(first, current_key_val(&it));
    assert!(it.advance());
    assert_eq!(second, current_key_val(&it));
    assert!(it.advance());
    assert_eq!(third, current_key_val(&it));
    // 测试 prev() 方法能否从第三个元素后退到第二个，再后退到第一个
    assert!(it.prev());
    assert_eq!(second, current_key_val(&it));
    assert!(it.prev());
    assert_eq!(first, current_key_val(&it));
    // 验证从第一个元素调用 prev() 应返回 false，且迭代器状态变为 !valid()
    assert!(!it.prev());
    assert!(!it.valid());
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_test_util_basic() {
        let v = vec![
            ("abc".as_bytes(), "def".as_bytes()),
            ("abd".as_bytes(), "deg".as_bytes()),
        ];
        let mut iter = TestLdbIter::new(v);
        assert_eq!(
            iter.next(),
            Some((Vec::from("abc".as_bytes()), Vec::from("def".as_bytes())))
        );
    }

    #[test]
    fn test_test_util_ldbiter_properties() {
        time_test!();
        let v;
        {
            time_test!("init");
            v = vec![
                ("abc".as_bytes(), "def".as_bytes()),
                ("abd".as_bytes(), "deg".as_bytes()),
                ("abe".as_bytes(), "deg".as_bytes()),
                ("abf".as_bytes(), "deg".as_bytes()),
            ];
        }
        test_iterator_properties(TestLdbIter::new(v));
    }
}
